/* 观察者模式（使用trait实现） */

pub trait Observer {
    fn update(&self, product: &str);
}

pub trait Subject {
    fn attach(&mut self, observer: Box<dyn Observer>);
    
    fn notify_observers(&self, product: &str);
}

pub struct Store {
    observers: Vec<Box<dyn Observer>>
}

impl Store {
    fn new() -> Store {
        Store {
            observers: Vec::new()
        }
    }
}

impl Subject for Store {
    fn attach(&mut self, observer: Box<dyn Observer>) {
        self.observers.push(observer);
    }

    fn notify_observers(&self, product: &str) {
        for observer in self.observers.iter() {
            observer.update(product);
        }
    }
}

#[derive(PartialEq)]
pub struct Customer {
    name: String
}

impl Observer for Customer {
    fn update(&self, product: &str) {
        println!("客户 [{}] 收到了新商品[{}]的通知", self.name, product);
    }
}

pub struct Vendor {
    name: String
}

impl Observer for Vendor {
    fn update(&self, product: &str) {
        println!("供应商 [{}] 收到了新商品[{}]的通知", self.name, product);
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_observer_trait_1() {
        let customer = Customer {name: String::from("张先生")};
        let vendor = Vendor{name: String::from("沃尔玛超时")};

        let mut store = Store::new();
        store.attach(Box::new(customer));
        store.attach(Box::new(vendor));

        store.notify_observers(&String::from("橘子"));
        store.notify_observers(&String::from("水蜜桃"));


    }
}